package morenoapp.components.welcome;

import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.HeadlessException;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JEditorPane;
import javax.swing.JOptionPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.Document;
import javax.swing.text.EditorKit;
import morenoapp.action.MorenoActions;
import morenoapp.MorenoApp;
import morenoapp.action.MorenoActionsFacade;
import morenoapp.action.resources.ActionsResourcesHolder;
import morenoapp.model.MorenoModelException;
import morenoapp.model.app.MorenoApplicationAdapter;
import morenoapp.model.app.MorenoApplicationData.ResourceDescriptor;
import morenoapp.util.I18N;
import morenoapp.util.MorenoUtil;

/**
 * Исследование
 * @author dmitry.mamonov
 */
public class WelcomeMainJPanel extends javax.swing.JPanel {
  /** Creates new form WelcomeMainJPanel */
  public WelcomeMainJPanel() {
    initComponents();
    initComponentsCustom();
  }

  /** This method is called from within the constructor to
   * initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is
   * always regenerated by the Form Editor.
   */
  @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPaneStart = new javax.swing.JScrollPane();
        jPanelStart = new javax.swing.JPanel();
        jButtonCreateNewResearch = new javax.swing.JButton();
        jScrollPaneRecentResearches = new javax.swing.JScrollPane();
        jEditorPaneRecentResearches = new javax.swing.JEditorPane();
        jScrollPaneWelcome = new javax.swing.JScrollPane();
        jEditorPaneWelcome = new javax.swing.JEditorPane();

        setName("Form"); // NOI18N

        jScrollPaneStart.setName("jScrollPaneStart"); // NOI18N

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance().getContext().getResourceMap(WelcomeMainJPanel.class);
        jPanelStart.setBackground(resourceMap.getColor("jPanelStart.background")); // NOI18N
        jPanelStart.setBorder(javax.swing.BorderFactory.createEmptyBorder(5, 5, 5, 5));
        jPanelStart.setName("jPanelStart"); // NOI18N
        jPanelStart.setPreferredSize(new java.awt.Dimension(400, 300));

        jButtonCreateNewResearch.setBackground(resourceMap.getColor("buttonWelcome.background")); // NOI18N
        jButtonCreateNewResearch.setForeground(resourceMap.getColor("buttonWelcome.foreground")); // NOI18N
        jButtonCreateNewResearch.setIcon(resourceMap.getIcon("buttonWelcome.icon")); // NOI18N
        jButtonCreateNewResearch.setText(resourceMap.getString("buttonWelcome.text")); // NOI18N
        jButtonCreateNewResearch.setName("buttonWelcome"); // NOI18N

        jScrollPaneRecentResearches.setBorder(null);
        jScrollPaneRecentResearches.setName("jScrollPaneRecentResearches"); // NOI18N

        jEditorPaneRecentResearches.setContentType(resourceMap.getString("editorRecentResearches.contentType")); // NOI18N
        jEditorPaneRecentResearches.setEditable(false);
        jEditorPaneRecentResearches.setText(resourceMap.getString("editorRecentResearches.text")); // NOI18N
        jEditorPaneRecentResearches.setCaretColor(resourceMap.getColor("editorRecentResearches.caretColor")); // NOI18N
        jEditorPaneRecentResearches.setName("editorRecentResearches"); // NOI18N
        jScrollPaneRecentResearches.setViewportView(jEditorPaneRecentResearches);

        jScrollPaneWelcome.setName("jScrollPaneWelcome"); // NOI18N

        jEditorPaneWelcome.setContentType(resourceMap.getString("jEditorPaneWelcome.contentType")); // NOI18N
        jEditorPaneWelcome.setEditable(false);
        jEditorPaneWelcome.setName("jEditorPaneWelcome"); // NOI18N
        try {
            jEditorPaneWelcome.setPage(getClass().getResource("welcome.html"));
        } catch (java.io.IOException e1) {
            e1.printStackTrace();
        }
        jScrollPaneWelcome.setViewportView(jEditorPaneWelcome);

        javax.swing.GroupLayout jPanelStartLayout = new javax.swing.GroupLayout(jPanelStart);
        jPanelStart.setLayout(jPanelStartLayout);
        jPanelStartLayout.setHorizontalGroup(
            jPanelStartLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelStartLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanelStartLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPaneWelcome, javax.swing.GroupLayout.DEFAULT_SIZE, 764, Short.MAX_VALUE)
                    .addGroup(jPanelStartLayout.createSequentialGroup()
                        .addComponent(jButtonCreateNewResearch, javax.swing.GroupLayout.PREFERRED_SIZE, 344, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jScrollPaneRecentResearches, javax.swing.GroupLayout.DEFAULT_SIZE, 410, Short.MAX_VALUE)))
                .addContainerGap())
        );
        jPanelStartLayout.setVerticalGroup(
            jPanelStartLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelStartLayout.createSequentialGroup()
                .addGroup(jPanelStartLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jButtonCreateNewResearch)
                    .addComponent(jScrollPaneRecentResearches, javax.swing.GroupLayout.PREFERRED_SIZE, 138, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPaneWelcome, javax.swing.GroupLayout.DEFAULT_SIZE, 425, Short.MAX_VALUE))
        );

        jScrollPaneStart.setViewportView(jPanelStart);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 798, Short.MAX_VALUE)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addGap(0, 0, 0)
                    .addComponent(jScrollPaneStart, javax.swing.GroupLayout.DEFAULT_SIZE, 798, Short.MAX_VALUE)
                    .addGap(0, 0, 0)))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 583, Short.MAX_VALUE)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addGap(0, 0, 0)
                    .addComponent(jScrollPaneStart, javax.swing.GroupLayout.DEFAULT_SIZE, 583, Short.MAX_VALUE)
                    .addGap(0, 0, 0)))
        );
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButtonCreateNewResearch;
    private javax.swing.JEditorPane jEditorPaneRecentResearches;
    private javax.swing.JEditorPane jEditorPaneWelcome;
    private javax.swing.JPanel jPanelStart;
    private javax.swing.JScrollPane jScrollPaneRecentResearches;
    private javax.swing.JScrollPane jScrollPaneStart;
    private javax.swing.JScrollPane jScrollPaneWelcome;
    // End of variables declaration//GEN-END:variables

  protected void refreshRecentFilesList() {
    final int listLimit = 5;
    List<ResourceDescriptor> recentFiles = MorenoApp.getApplicationData().getRecentOpennedResouces();
    if (recentFiles.size() > listLimit) {
      recentFiles = recentFiles.subList(0, listLimit);
    }

    StringBuilder builder = new StringBuilder("<html>"); //NOI18N <font face='Times New Roman'>
    builder.append("<b>" + I18N.get("label.recent_researches") + ":</b><br/>\n");
    if (recentFiles.size() == 0) {
      builder.append("<font color='gray'>" + I18N.get("label.no_recent_researches") + "</font>");
    } else {
      int index = 0;
      for (ResourceDescriptor rd : recentFiles) {
        index++;
        builder.append("<a href=\"file://" + rd.getLastAccessTime().getTime() + "\">" + index + ". " + new File(rd.getResource()).getName() + " (" + MorenoUtil.dateToStringDate(rd.getLastAccessTime()) + ")</a><br/>\n"); //NOI18N
      }
    }

    jEditorPaneRecentResearches.setText(builder.toString());
  }

    private void initComponentsCustom() throws NumberFormatException, HeadlessException {
        { //welcome text
            JEditorPane text = jEditorPaneWelcome;
            text.setContentType("text/html");
            text.getDocument().putProperty("IgnoreCharsetDirective", Boolean.TRUE);
            try {
                InputStream pageDataStream = getClass().getResourceAsStream("welcome.html");
                if (pageDataStream!=null){
                    //instead of:
                    //this -> String html = IOUtils.toString(pageDataStream, "UTF-8");
                    //and this-> text.setText(html);
                    //we will use this to ensure text encoding:
                    Document doc = text.getDocument();
                    doc.remove(0, doc.getLength());
                    Reader r = new InputStreamReader(pageDataStream,"UTF-8");
                    EditorKit kit = text.getEditorKit();
                    kit.read(r, doc, 0);
                } else {
                    text.setText(I18N.get("welcome.error_no_welcome_page_resource"));
                }
            } catch (Exception ex) {
                text.setText(I18N.get("welcome.error_no_welcome_page")+"\n"+
                            MorenoUtil.toStirng(ex));
            }

            text.setEditable(false);
        }

        //Информационная панель
        {
            jEditorPaneWelcome.addHyperlinkListener(new WelcomeHyperlinkListener() {
                @Override
                protected void doOperartion(URI uri) throws Exception {
                    Desktop.getDesktop().browse(uri);
                }
            });
        }
        //Обработка списка последних документов
        {
            //Привязка слушателя к визуальному компоненту.
            jEditorPaneRecentResearches.addHyperlinkListener(new WelcomeHyperlinkListener() {
                @Override
                protected void doOperartion(URI uri) {
                    List<ResourceDescriptor> recentResources = MorenoApp.getApplicationData().getRecentOpennedResouces();
                    String resourceTimestampStr = uri.getHost();
                    long resourceTimestampLong = Long.parseLong(resourceTimestampStr);
                    ResourceDescriptor targetResource = null;
                    for (ResourceDescriptor rd : recentResources) {
                        if (rd.getLastAccessTime().getTime() == resourceTimestampLong) {
                            targetResource = rd;
                            break;
                        }
                    }
                    if (targetResource != null) {
                        try {
                            MorenoApp.getApplicationData().loadModel(new File(targetResource.getResource()));
                            SwingUtilities.invokeLater(new Runnable() {
                                public void run() {
                                    MorenoActions.getInstance().actionNavigateStartWork();
                                }
                            });
                        } catch (MorenoModelException ex) {
                            Logger.getLogger(WelcomeMainJPanel.class.getName()).log(Level.SEVERE, null, ex);
                            JOptionPane.showMessageDialog(WelcomeMainJPanel.this, I18N.get("message.can_not_open_document_colon") + ex.getMessage());
                        }
                    } else {
                        JOptionPane.showMessageDialog(WelcomeMainJPanel.this, I18N.get("message.can_not_open_document"));
                    }
                }
            });
            //Добавляем слушателя модели приложения что бы основлять список
            //последних открытых документов.
            MorenoApp.getApplicationData().addApplicationListener(new MorenoApplicationAdapter() {
                @Override
                public void afterModelOpened(File source) {
                    refreshRecentFilesList();
                }

                @Override
                public void afterModelSaved(File target) {
                    refreshRecentFilesList();
                }
            });
            jButtonCreateNewResearch.setAction(MorenoActionsFacade.getActionCreateNewModel());
            jButtonCreateNewResearch.setIcon(ActionsResourcesHolder.ICON_ACTION_NEW_128);
            jButtonCreateNewResearch.setFont(jButtonCreateNewResearch.getFont().deriveFont(24.0f));
            jButtonCreateNewResearch.setText(I18N.get("welcome.create_new_research"));
            //Обновление списка последних документов.
            refreshRecentFilesList();
        }
    }

  protected abstract class WelcomeHyperlinkListener implements HyperlinkListener {
    public void hyperlinkUpdate(final HyperlinkEvent e) {
      final JEditorPane source = (JEditorPane) e.getSource();
      if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) {
        source.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            try {
              doOperartion(e.getURL().toURI());
            } catch (Exception ex) {
              Logger.getLogger(WelcomeMainJPanel.class.getName()).log(Level.WARNING, null, ex);
              JOptionPane.showMessageDialog(SwingUtilities.getRoot(WelcomeMainJPanel.this), I18N.get("message.can_not_open_link_colon") + e.getURL());
            } finally {
              source.setCursor(Cursor.getDefaultCursor());
            }
          }
        });
        
      } else if (e.getEventType().equals(HyperlinkEvent.EventType.ENTERED)) {
        source.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
      } else if (e.getEventType().equals(HyperlinkEvent.EventType.EXITED)) {
        source.setCursor(Cursor.getDefaultCursor());
      }
    }

    protected abstract void doOperartion(URI uri) throws Exception;
  }
}
